// 统一API客户端
// 提供Tauri命令调用、错误处理、重试机制、缓存等功能

import { invoke } from '@tauri-apps/api/core';
import { listen, UnlistenFn } from '@tauri-apps/api/event';

// API响应类型
export interface ApiResponse<T = any> {
  success: boolean;
  data?: T;
  error?: string;
  timestamp: string;
  requestId?: string;
}

// API错误类型
export interface ApiError {
  code: string;
  message: string;
  details?: any;
  timestamp: string;
  requestId?: string;
}

// 请求配置
export interface RequestConfig {
  timeout?: number;
  retries?: number;
  retryDelay?: number;
  cache?: boolean;
  cacheKey?: string;
  cacheTTL?: number;
  signal?: AbortSignal;
}

// 默认配置
const DEFAULT_CONFIG: Required<RequestConfig> = {
  timeout: 30000,
  retries: 3,
  retryDelay: 1000,
  cache: false,
  cacheKey: '',
  cacheTTL: 300000, // 5分钟
  signal: new AbortController().signal,
};

// 缓存项
interface CacheItem<T> {
  data: T;
  timestamp: number;
  ttl: number;
}

// API客户端类
export class ApiClient {
  private cache = new Map<string, CacheItem<any>>();
  private requestQueue = new Map<string, Promise<any>>();
  private eventListeners = new Map<string, UnlistenFn>();

  // 执行Tauri命令
  async invoke<T = any>(
    command: string,
    args?: Record<string, any>,
    config: RequestConfig = {}
  ): Promise<T> {
    const finalConfig = { ...DEFAULT_CONFIG, ...config };
    const requestId = this.generateRequestId();
    const cacheKey = config.cacheKey || this.generateCacheKey(command, args);

    // 检查缓存
    if (finalConfig.cache) {
      const cached = this.getFromCache<T>(cacheKey);
      if (cached) {
        return cached;
      }
    }

    // 检查是否有相同的请求正在进行
    if (this.requestQueue.has(cacheKey)) {
      return this.requestQueue.get(cacheKey);
    }

    // 创建请求Promise
    const requestPromise = this.executeRequest<T>(
      command,
      args,
      finalConfig,
      requestId
    );

    // 添加到请求队列
    this.requestQueue.set(cacheKey, requestPromise);

    try {
      const result = await requestPromise;

      // 缓存结果
      if (finalConfig.cache) {
        this.setCache(cacheKey, result, finalConfig.cacheTTL);
      }

      return result;
    } finally {
      // 从请求队列中移除
      this.requestQueue.delete(cacheKey);
    }
  }

  // 执行请求（带重试）
  private async executeRequest<T>(
    command: string,
    args: Record<string, any> = {},
    config: Required<RequestConfig>,
    requestId: string
  ): Promise<T> {
    let lastError: Error | null = null;

    for (let attempt = 0; attempt <= config.retries; attempt++) {
      try {
        // 检查是否被取消
        if (config.signal.aborted) {
          throw new Error('Request aborted');
        }

        // 执行命令
        const result = await Promise.race([
          invoke<ApiResponse<T>>(command, { ...args, requestId }),
          this.createTimeoutPromise(config.timeout),
        ]);

        // 处理响应
        if (result.success) {
          return result.data as T;
        } else {
          throw new ApiError({
            code: 'API_ERROR',
            message: result.error || 'Unknown API error',
            timestamp: result.timestamp,
            requestId: result.requestId,
          });
        }
      } catch (error) {
        lastError = error as Error;

        // 如果是最后一次尝试，抛出错误
        if (attempt === config.retries) {
          break;
        }

        // 等待重试延迟
        await this.delay(config.retryDelay * Math.pow(2, attempt));
      }
    }

    throw lastError;
  }

  // 监听事件
  async listen<T = any>(
    event: string,
    handler: (data: T) => void
  ): Promise<UnlistenFn> {
    const unlisten = await listen<T>(event, (event) => {
      handler(event.payload);
    });

    this.eventListeners.set(event, unlisten);
    return unlisten;
  }

  // 取消监听事件
  async unlisten(event: string): Promise<void> {
    const unlisten = this.eventListeners.get(event);
    if (unlisten) {
      unlisten();
      this.eventListeners.delete(event);
    }
  }

  // 批量执行命令
  async batch<T = any>(
    requests: Array<{
      command: string;
      args?: Record<string, any>;
      config?: RequestConfig;
    }>
  ): Promise<T[]> {
    const promises = requests.map(({ command, args, config }) =>
      this.invoke<T>(command, args, config)
    );

    return Promise.all(promises);
  }

  // 清除缓存
  clearCache(pattern?: string): void {
    if (pattern) {
      const regex = new RegExp(pattern);
      for (const [key] of this.cache) {
        if (regex.test(key)) {
          this.cache.delete(key);
        }
      }
    } else {
      this.cache.clear();
    }
  }

  // 获取缓存统计
  getCacheStats(): {
    size: number;
    keys: string[];
    totalMemory: number;
  } {
    const keys = Array.from(this.cache.keys());
    const totalMemory = JSON.stringify(Array.from(this.cache.values())).length;

    return {
      size: this.cache.size,
      keys,
      totalMemory,
    };
  }

  // 清理过期缓存
  cleanupCache(): void {
    const now = Date.now();
    for (const [key, item] of this.cache) {
      if (now - item.timestamp > item.ttl) {
        this.cache.delete(key);
      }
    }
  }

  // 销毁客户端
  destroy(): void {
    // 取消所有事件监听
    for (const unlisten of this.eventListeners.values()) {
      unlisten();
    }
    this.eventListeners.clear();

    // 清除缓存
    this.cache.clear();

    // 清除请求队列
    this.requestQueue.clear();
  }

  // 私有方法
  private generateRequestId(): string {
    return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }

  private generateCacheKey(command: string, args?: Record<string, any>): string {
    const argsStr = args ? JSON.stringify(args) : '';
    return `${command}:${btoa(argsStr)}`;
  }

  private getFromCache<T>(key: string): T | null {
    const item = this.cache.get(key);
    if (!item) return null;

    const now = Date.now();
    if (now - item.timestamp > item.ttl) {
      this.cache.delete(key);
      return null;
    }

    return item.data;
  }

  private setCache<T>(key: string, data: T, ttl: number): void {
    this.cache.set(key, {
      data,
      timestamp: Date.now(),
      ttl,
    });
  }

  private createTimeoutPromise(timeout: number): Promise<never> {
    return new Promise((_, reject) => {
      setTimeout(() => {
        reject(new Error(`Request timeout after ${timeout}ms`));
      }, timeout);
    });
  }

  private delay(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

// 自定义API错误类
export class ApiError extends Error {
  public code: string;
  public details?: any;
  public timestamp: string;
  public requestId?: string;

  constructor(error: {
    code: string;
    message: string;
    details?: any;
    timestamp: string;
    requestId?: string;
  }) {
    super(error.message);
    this.name = 'ApiError';
    this.code = error.code;
    this.details = error.details;
    this.timestamp = error.timestamp;
    this.requestId = error.requestId;
  }
}

// 全局API客户端实例
export const apiClient = new ApiClient();

// 自动清理缓存
setInterval(() => {
  apiClient.cleanupCache();
}, 60000); // 每分钟清理一次

// 导出类型
export type { RequestConfig, ApiResponse };
